package xiaoa.java.zk;

import java.util.ArrayList;
import java.util.List;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.data.Stat;

import xiaoa.java.log.L;
import xiaoa.java.utils.ObjectUtis;

/**
 * 
 * @author xiaoa
 * @date 2016年12月30日 下午4:52:55
 * @version V1.0
 *
 */
public class ZookeeperMgr {
	
	//  链接配置
	private static RetryPolicy  policy        =   null;
	
	// 链接客户端
	private static CuratorFramework  client   =  null;
	
	// 链接集合
	private static List<String>      connList =  new ArrayList<String>();
	
	/**
	 * 获取链接
	 * @Title: getConnString
	 * @return
	 * @author xiaoa
	 */
	private static String getConnString(){
		
		if(connList == null || connList.isEmpty()){
			throw new RuntimeException("没有可用链接");
		}
		StringBuilder  connSb  = new StringBuilder();
		
		for(String conn : connList){
			
			if(connSb.length() != 0){
				connSb.append(",");
			}
			connSb.append(conn);
		}
		
		return connSb.toString();
	}
	
	/**
	 * 初始化
	 * @throws Throwable
	 */
    public static void init(String... conns)throws Throwable{
    	
    	// 添加连接池
    	if(conns != null){
	    	for(String conn : conns){
	    		
	    		if(conn != null && !conn.trim().equals("")){
	    			addConn(conn);
	    		}
	    	}
    	}
    	  
//      初始化连接配置   ZooKeeper每1秒检查⼀一次session状态，如果断
//    	掉的话，重新连接，如果连续3次均没连上，则session失
//    	效
    	policy  = new ExponentialBackoffRetry(1000, 3);  
    	
    	// 创建一个链接
    	client  = CuratorFrameworkFactory.newClient(getConnString(), policy);
    	
    	// 启动
    	client.start();
    	
    	// 日志
    	L.info("========= 初始化 zk  servers  = " +  ObjectUtis.toMerge("," , conns));
    	
    }

    
    /**
     * 添加一个链接
     * @Title: addConn
     * @param conn
     * @author xiaoa
     */
    public static void addConn(String conn){
    	connList.add(conn);
    }
    
    /**
     * 获取值
     * @Title: get
     * @param path
     * @return
     * @throws Throwable
     * @author xiaoa
     */
    public static String get(String path)throws Throwable{
    	
    	byte[]  bs =  client.getData().forPath(path);
    	
    	if(bs == null || bs.length == 0){
    		return "";
    	}
    	
    	return new String(bs);
    }
    
    /**
     * 获取所有子节点
     * @Title: getClients
     * @param path
     * @return
     * @author xiaoa
     */
    public static List<String> getClients(String path)throws Throwable{
    	
    	if(path == null || path.isEmpty()){
    		throw new RuntimeException("参数有误");
    	}
    	
    	List<String>  clients  =  client.getChildren().forPath(path);
    	
    	return clients;
    	
    }
	
    /**
     * 判断
     * @Title: exists
     * @param path
     * @return
     * @throws Throwable
     * @author xiaoa
     */
    public static boolean exists(String path)throws Throwable{

    	if(path == null || path.isEmpty()){
    		throw new RuntimeException("参数有误");
    	}
    	
    	Stat  state  = client.checkExists().forPath(path);
    	
    	if(state == null){
    		return false;
    	}
    	
    	return true;
    }
    

    /**
     * 创建一个节点
     * @Title: create
     * @param path
     * @throws Throwable
     * @author xiaoa
     */
    public static void insert(String path , String  value)throws Throwable{
    	if(path == null || path.equals("")){
    		throw new RuntimeException("参数有误");
    	}
    	
    	// 创建节点  如果没有父节点创建节点
    	client.create().creatingParentContainersIfNeeded().forPath(path , value.getBytes());
    	
    }
    
    /**
     * 删除节点
     * @Title: delete
     * @param path
     * @throws Throwable
     * @author xiaoa
     */
    public static void delete(String path)throws Throwable{
    	
    	if(path == null || path.equals("")){
    		throw new RuntimeException("参数有误");
    	}
    	
    	client.delete().guaranteed().forPath(path);
    }
    
    
    
    /**
     * 修改节点值
     * @Title: update
     * @param path
     * @param value
     * @throws Throwable
     * @author xiaoa
     */
    public static void update(String path , String  value)throws Throwable{
    	if(path == null || path.equals("")){
    		throw new RuntimeException("参数有误");
    	}
    	
    	// 修改节点值
    	client.setData().forPath(path , value.getBytes());
    	
    }    
    
    
    /**
     * 插入或者更新
     * @Title: insetOrupdate
     * @param path
     * @param value
     * @throws Throwable
     * @author xiaoa
     */
    public static void insetOrupdate(String path , String  value)throws Throwable{
    	if(path == null || path.equals("")){
    		throw new RuntimeException("参数有误");
    	}
    	
    	if (exists(path)){
    		update(path, value);
    	}else {
    		insert(path, value);
    	}
    	
    }    
    
    
    public static void main(String[] args)throws Throwable {
    	
    	// 添加url
		addConn("xiaoa1:2181");
		
		init();
		
		//System.out.println(path.equals(""));
		
		update("/test/xiaoaName", "{name:‘个哈哈’}");

		// 获取一个节点值
		String name = get("/test/xiaoaName");
		
		System.out.println(name);
		
		// 获取一个节点下一层子节点
		List<String>  clients  = getClients("/test");
		
		System.out.println(clients);
		
		// 判断一个节点是否存在
		System.out.println(exists("/test"));
		System.out.println(exists("/test____"));
		
//		delete("/test____/test/test/test");
//		
//		create("/test____/test/test/test", "");
		System.out.println(exists("/test____/test/test/test"));
	}
	

}
